package com.ctshk.rpc.payment.strategy.impl;

import com.alibaba.fastjson.JSON;
import com.ctshk.common.enums.SystemError;
import com.ctshk.common.utils.Assert;
import com.ctshk.rpc.payment.dto.MasterCardPayConfig;
import com.ctshk.rpc.payment.dto.MastercardPayHostedDto;
import com.ctshk.rpc.payment.dto.PayDetailsDTO;
import com.ctshk.rpc.payment.dto.RefundDetailsDTO;
import com.ctshk.rpc.payment.dto.rep.mastercard.HostedSession;
import com.ctshk.rpc.payment.dto.rep.mastercard.QueryTransactionDTO;
import com.ctshk.rpc.payment.dto.req.PayRefundReq;
import com.ctshk.rpc.payment.entity.PayRecord;
import com.ctshk.rpc.payment.enums.PayOrderStatus;
import com.ctshk.rpc.payment.enums.PaymentMethod;
import com.ctshk.rpc.payment.factory.PayDetailsDTOSimpleFactory;
import com.ctshk.rpc.payment.req.PayCommonReq;
import com.ctshk.rpc.payment.strategy.PayStrategy;
import com.ctshk.rpc.payment.utils.PayUtil;
import com.ctshk.rpc.payment.utils.mastercard.ApiRequest;
import com.ctshk.rpc.payment.utils.mastercard.ApiRequestService;
import com.ctshk.rpc.payment.utils.mastercard.ApiResponseService;
import com.ctshk.rpc.payment.utils.mastercard.MastercardRestApiClient;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;

/**
 * @BelongsProject: ctshk-cloud
 * @BelongsPackage: com.ctshk.rpc.payment.strategy.impl
 * @Author: hef
 * @CreateTime: 2021-04-28 09:48
 * @Description: 描述
 */
@Slf4j
@Component
public class MastercardPayHostedStrategy extends PayStrategy<MasterCardPayConfig> {
    public MastercardPayHostedStrategy() {
        super(MasterCardPayConfig.class, PaymentMethod.VISA_MASTERCARD_HOSTED);
    }

    @Value("${spring.profiles.active}")
    private String active;
    @Value("${pay.local-gateway}")
    private String LOCAL_GATEWAY;
    private static final String TEMP_HTML = "<html><head><script src=\"https://ap-gateway.mastercard.com/checkout/version/49/checkout.js\"data-error=\"errorCallback\"data-cancel=\"cancelCallback\"></script><script type=\"text/javascript\">function errorCallback(error){console.log(JSON.stringify(error))}function cancelCallback(){console.log('Payment cancelled')}Checkout.configure({merchant:'%s',order:{description:'%s',id:'%s'},session:{id:'%s'},interaction:{merchant:{name:'%s',address:{line1:'200 Sample St',line2:'1234 Example Town'}}}});</script></head><body>...<input type=\"button\"value=\"Pay with Lightbox\"onclick=\"Checkout.showLightbox();\"/><input type=\"button\"value=\"Pay with Payment Page\"onclick=\"Checkout.showPaymentPage();\"/>...</body><script>window.onload=function(){Checkout.showPaymentPage()}</script></html>";

    @Override
    public Object pay(PayCommonReq req) {
        //请求地址
        MasterCardPayConfig config = getConfig();
        String reqJson = ApiRequest
                .builder()
                .apiOperation("CREATE_CHECKOUT_SESSION")
                .orderId(String.valueOf(req.getOrderId()))
                .orderAmount(req.getTotalFee().toString())
                .orderCurrency(req.getCurrency().getCode())
                .orderNotificationUrl(config.getNotifyUrl())
                .build().buildReqJson();
        String requestUrl = ApiRequestService.getSessionRequestUrl(config);
        HostedSession hostedSession = null;
        try {
            log.info("【支付服务-Visa/Master支付】第三方API请求, url:{}, data:{}, config:{}", requestUrl, JSON.toJSONString(reqJson), JSON.toJSONString(config));
            String resp = MastercardRestApiClient.postTransaction(reqJson, requestUrl, config);
            log.info("【支付服务-Visa/Master支付】第三方API响应, data:{}", resp);
            hostedSession = ApiResponseService.parseSessionResponse(resp);
        } catch (Exception e) {
            e.printStackTrace();
        }
        Assert.nonNull(hostedSession, SystemError.PAY_22003);
        MastercardPayHostedDto mastercardPayHostedDto = new MastercardPayHostedDto();
        mastercardPayHostedDto.setMerchantId(config.getMerchantId());
        mastercardPayHostedDto.setMerchantName(config.getMerchantName());
        mastercardPayHostedDto.setAmount(req.getTotalFee());
        mastercardPayHostedDto.setOrderNumber(String.valueOf(req.getOrderId()));
        mastercardPayHostedDto.setCurrency(req.getCurrency().getCode());
        mastercardPayHostedDto.setOrderDescription(req.getBody());
        mastercardPayHostedDto.setSessionId(hostedSession.getId());
        mastercardPayHostedDto.setSessionVersion(hostedSession.getVersion());
        mastercardPayHostedDto.setSessionSuccessIndicator(hostedSession.getSuccessIndicator());
        HashMap<String, String> paramMap = new HashMap<>();
        paramMap.put("sessionId", hostedSession.getId());
        paramMap.put("merchantId", config.getMerchantId());
        paramMap.put("merchantName", config.getMerchantName());
        paramMap.put("orderId", String.valueOf(req.getOrderId()));
        paramMap.put("orderDescription", req.getBody());
        String url = PayUtil.generateGetUrl(LOCAL_GATEWAY + "/app/payment/pay/temp/callPay", StandardCharsets.UTF_8.name(), paramMap);
//        String htmlStr = String.format(TEMP_HTML, config.getMerchantId(), req.getBody(), req.getOrderId(), hostedSession.getId(), config.getMerchantName());
        log.info("【支付服务-Visa/Master支付】构建后的字符串, data:{}", url);
        return url;
    }

    public static void main(String[] args) {
        System.out.println(StandardCharsets.UTF_8.name());
    }

    @Override
    protected boolean payCallback(Map<String, String> paramMap) {
        String callbackJson = JSON.toJSONString(paramMap);
        System.err.println("**********************************收到Mastercard支付回调************************************\r" + callbackJson);
        //转换对象
//        QueryTransactionDTO dto = JSON.parseObject(callbackJson, QueryTransactionDTO.class);
//        Assert.isTrue(dto != null && dto.getOrder() != null, SystemError.PAY_22018);
//        QueryTransactionDTO.Order order = dto.getOrder();
        String oderJson = paramMap.get("order");
        QueryTransactionDTO.Order order = JSON.parseObject(oderJson, QueryTransactionDTO.Order.class);
        Assert.nonNull(order, SystemError.PAY_22018);
        //获取支付记录
        PayRecord payRecord = payRecordMapper.selectByOrderId(Long.valueOf(order.getId()));
        Assert.nonNull(payRecord, SystemError.PAY_22004);
        //校验金额
        BigDecimal amount = order.getAmount();
        /*if ("local".equals(active) || "test".equals(active)) {
            Assert.isTrue(new BigDecimal("0.1").compareTo(amount) == 0, SystemError.PAY_22015);
        } else {
            Assert.isTrue(payRecord.getTotalFee().compareTo(amount) == 0, SystemError.PAY_22015);
        }*/
        Assert.isTrue(payRecord.getTotalFee().compareTo(amount) == 0, SystemError.PAY_22015);
        PayOrderStatus status = "CAPTURED".equals(order.getStatus()) ? PayOrderStatus.FULFIL : PayOrderStatus.PAYMENT_ERROR;
        //修改记录
        PayRecord update = new PayRecord();
        update.setId(payRecord.getId());
        update.setCallbackParam(callbackJson);
        update.setOrderStatus(status.getStatus());
        update.setGmtModified(LocalDateTime.now());
        update.setPayTime(LocalDateTime.now());
        int i = payRecordMapper.updateById(update);
        return i > 0;
    }


    @Override
    public PayDetailsDTO getPayDetails(String orderNumber) {
        MasterCardPayConfig config = getConfig();
        String reqUrl = ApiRequestService.getOrderRequestUrl(config, orderNumber);
        String result = null;
        try {
            result = MastercardRestApiClient.getTransaction(reqUrl, config);
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.err.println("*********************查询MasterCard交易信息返回数据*********************\r" + result);
        Assert.notBlank(result, SystemError.PAY_22004);
        QueryTransactionDTO dto = JSON.parseObject(result, QueryTransactionDTO.class);
        return PayDetailsDTOSimpleFactory.produce(dto);
    }


    @Override
    protected boolean checkPayDetails(Map<String, String> paramMap) {
//        QueryTransactionDTO dto = JSON.parseObject(JSON.toJSONString(paramMap), QueryTransactionDTO.class);
//        QueryTransactionDTO.Order order = dto.getOrder();
        String oderJson = paramMap.get("order");
        QueryTransactionDTO.Order order = JSON.parseObject(oderJson, QueryTransactionDTO.Order.class);
        PayDetailsDTO payDetails = getPayDetails(order.getId());
        Assert.isTrue(payDetails.getOrderAmount().compareTo(order.getAmount()) == 0
                        && order.getStatus().equals(payDetails.getPrimaryStatus())
                , SystemError.PAY_22017);
        return true;
    }


    @Override
    public boolean refund(PayRefundReq req) {
        //TODO 商户未开通线上退款 直接抛异常
        Assert.isTrue(false, SystemError.PAY_22012, "信用卡");
        MasterCardPayConfig config = getConfig();
        String reqUrl = ApiRequestService.getOrderRequestUrl(config,
                req.getOrderNumber(),
                req.getRefundNumber());
        String reqJson = ApiRequest.builder()
                .apiOperation("REFUND")
                .transactionAmount(req.getRefundAmount().toString())
                .transactionCurrency(req.getCurrency()).build().buildReqJson();
        String result = null;
        try {
            result = MastercardRestApiClient.sendTransaction(reqJson, reqUrl, config);
        } catch (Exception e) {
            e.printStackTrace();
        }
        Assert.notBlank(result, SystemError.PAY_22006);
        return false;
    }

    @Override
    public RefundDetailsDTO getRefundDetail(String orderNumber, String refundNumber) {
        // TODO 商户号不支持线上退款
        Assert.isTrue(false, SystemError.PAY_22012, "信用卡");
        return null;
    }

    @Override
    public Object refundNotify(Map<String, String> paramMap) {
        // TODO 商户号不支持线上退款
        return null;
    }
}
